<?php
namespace Kuoqi\FileDriver;
use Kuoqi\Config;
use Kuoqi\FileDriver;
use Kuoqi\Format;
use Kuoqi\FileDriver\Mime;

/**
 * Class Upload
 * @package Kuoqi\FileDriver
 * User kuoqi
 * Datetime 2022/3/8 10:38
 * Remark 文件上传，针对单文件上传，如果涉及多文件上传，可手动初始化多个文件
 */
class Upload{


    /**
     * @var array
     * User kuoqi
     * Datetime 2022/3/8 10:41
     * Remark  上传文件信息，需要符合php规范
     */
    protected $arraybyform = array();

    /**
     * @var null
     * User kuoqi
     * Datetime 2022/3/8 10:53
     * Remark 上传文件实例
     */
    protected $file_input = null;

    /**
     * @var null
     * User kuoqi
     * Datetime 2022/3/8 11:37
     * Remark 正式上传文件相关信息
     */
    protected $file_upload = null;
    /**
     * @var string
     * User kuoqi
     * Datetime 2022/3/8 10:35
     * Remark 错误信息
     */
    public $errmsg = '';

    /**
     * @var bool
     * User kuoqi
     * Datetime 2022/3/8 10:35
     * Remark 是否验证通过字段
     */
    protected $is_valied = true;


    /**
     * @var int
     * User kuoqi
     * Datetime 2022/3/8 11:06
     * Remark 检测文件上传大小限制,单位byte,默认2M
     */
    protected $max_size = '2M';

    /**
     * @var array
     * User kuoqi
     * Datetime 2022/3/8 11:32
     * Remark 上传mime列表信息
     */
    public $mimelist = array();

    /**
     * @var array
     * User kuoqi
     * Datetime 2022/3/8 12:38
     * Remark 文件信息
     */
    public $info = array();//

    /**
     * @var string
     * User kuoqi
     * Datetime 2022/3/9 13:28
     * Remark 文件上传保存路径，不带时间后面的部分
     */
    public $upload_path = '';//


    /**
     * Upload constructor.
     * @param null $upfile 系统上传文件对象信息，每次只支持一个
     */
    public function __construct($upfile = null)
    {
        //判定是否有上传文件对象写入，没有则自动初始化最后一个上传文件
        $this->arraybyform = $upfile?$upfile:array_pop($_FILES);
        //兼容当前文件，这个是单个文件上传的模块，检测当前文件是否为可写入文件
        $this->max_size = Config('UPLOAD_MAX_SIZE');
        $this->mimelist = Mime::mimelist();
        $this->upload_path = Config::get('DS').Config::get('PATH_UPLOAD');

    }

    //使用图片合集的mime
    public function useMimeImage(){
        $this->mimelist = Mime::mimeimagelist();
    }

    /**
     * 检测上传文件完整性
     * User kuoqi
     * Datetime 2022/3/30 13:57
     * Remark
     */
    public function checkFile(){
        $this->is_valied&&$this->checkFileExist();//核验文件对象是否正确
        $this->is_valied&&$this->checkFileComplete();//检验文件完整性
        $this->is_valied&&$this->checkFileRead();//检验文件是否可读
        $this->is_valied&&$this->checkFileMaxWithSystem();//检验文件大小是否超过系统限制
        $this->is_valied&&$this->checkFileMax();//检验文件大小是否操作当前设置
        $this->is_valied&&$this->checkFileMime();//检验文件类型是否可以上传
        return $this->is_valied;
    }

    /**
     * User kuoqi
     * Datetime 2022/3/8 10:48
     * Remark 核验文件对象是否正确
     */
    final function checkFileExist()
    {
        if(!(is_array($this->arraybyform)&&(count($this->arraybyform)==5))){
            $this->errmsg = 'file upload error with no file';
            $this->is_valied = false;
            return;
        }
    }

    /**
     * User kuoqi
     * Datetime 2022/3/8 10:56
     * Remark 检验文件完整性
     */
    final function checkFileComplete()
    {
        if($this->arraybyform['error']!=0){
            $this->errmsg = 'upload_file is not complete';
            $this->is_valied = false;
            return;
        }
    }

    /**
     * User kuoqi
     * Datetime 2022/3/8 10:56
     * Remark 检验文件是否可读
     */
    final function checkFileRead()
    {
        if(!is_file($this->arraybyform['tmp_name'])){
            $this->errmsg = 'upload_file tmp folder can not writable';
            $this->is_valied = false;
            return;
        }
        if(!is_readable($this->arraybyform['tmp_name'])){
            $this->errmsg = 'upload_file tmp can not readabled';
            $this->is_valied = false;
            return ;
        }
    }

    /**
     * User kuoqi
     * Datetime 2022/3/8 11:25
     * Remark checkFileMaxWithSystem
     */
    public function checkFileMaxWithSystem(){
        $size = ini_get('upload_max_filesize');
        $size = Format::str2byte($size);
        if($this->arraybyform['size']>$size){
            $this->errmsg = 'file_size not greater than php.ini upload_max_filesize';
            $this->is_valied = false;
            return;
        }
    }

    /**
     * User kuoqi
     * Datetime 2022/3/8 11:26
     * Remark 检测文件上传大小是否操作当前配置大小
     */
    public function checkFileMax()
    {
        $size = Format::str2byte($this->max_size);
        if($this->arraybyform['size']>$size){
            $this->errmsg = 'file_size not greater than setting max_size';
            $this->is_valied = false;
            return;
        }
    }

    /**
     * User kuoqi
     * Datetime 2022/3/8 11:33
     * Remark 检测文件mime是否在克上传列表中
     */
    public function checkFileMime()
    {
        if(!in_array($this->arraybyform['type'],$this->mimelist)){
            $this->errmsg = 'file_mime not in list mime with '.$this->arraybyform['type'].' and library is '.json_encode($this->mimelist);
            $this->is_valied = false;
            return;
        }
    }

    /**
     * @return null|string
     * User kuoqi
     * Datetime 2022/3/8 12:43
     * Remark 获取当前文件的ext
     */
    public function getExt(){
        //尝试获取当前文件是否有ext
        $ext = strrchr($this->arraybyform['name'],'.');
        if(!$ext){
            $ext = Mime::mime2ext($this->arraybyform['type']);
        }
        return $ext;
    }

    /**
     * 具体执行函数信息
     * @param string $upfile
     * @return bool
     * User kuoqi
     * Datetime 2022/3/25 15:38
     * Remark
     */
    public function upload($upfile = ''){
        if($upfile){ $this->arraybyform = $upfile;}
        $this->is_valied = true;//初始化字段信息
        $this->errmsg = 'upload success';//初始化错误信息
        $this->checkFile();//核验上传文件前置操作
        if(!$this->is_valied){ return $this->isValied(); }//文件验证失败的情况下，直接返回错误信息
        //$this->is_valied&&$this->initFileInput();//初始化上传文件
        //$this->is_valied&&$this->initFileUpload();//初始化上传文件
        $ext = $this->getExt();
        $path = $this->upload_path.
            Config::get('DS').substr($ext,1).Config::get('DS').date('ymd');
        $filename = md5($path.time().rand(1000,9999)).$ext;
        $file = new FileDriver($path.Config::get('DS').$filename);
        if(!$file->checkPath()){
            $this->errmsg = 'file['.$this->arraybyform['name'].']move error ->'.$file->getError();
            $this->is_valied = false;
            return false;
        }
        if(move_uploaded_file($this->arraybyform['tmp_name'],$file->getFullfile())){
            $this->info['mime'] = $this->arraybyform['type'];
            $this->info['ext'] = $ext;
            $this->info['name'] = $this->arraybyform['name'];
            $this->info['filename'] = $file->getFilename();
            $this->info['url'] = $file->getUrl();
            $this->info['size'] = $this->arraybyform['size'];
            $this->info['md5'] = $file->getMd5();
            $this->info['fullpath'] = $file->getFullfile();
            return true;
        }else{
            $this->errmsg = '文件['.$this->arraybyform['name'].']移动失败';
            $this->is_valied = false;
            return false;
        }
    }

    /**
     * @return array
     * User kuoqi
     * Datetime 2022/3/8 10:27
     * Remark 专业返回当前对象信息
     */
	public function info()
    {
		return $this->info;	
	}

    /**
     * @return bool
     * User kuoqi
     * Datetime 2022/3/8 12:39
     * Remark 验证是佛成功
     */
	public function isValied()
    {
	    return $this->is_valied;
    }

    /**
     * @return string
     * User kuoqi
     * Datetime 2022/3/8 12:39
     * Remark 获取错误信息
     */
	public function getError()
    {
		return $this->errmsg;
	}

    /**
     * 获取上传文件的md5
     * @return string
     * User kuoqi
     * Datetime 2022/3/25 15:41
     * Remark
     */
    public function md5(){
        $md5 = md5(file_get_contents($this->arraybyform['tmp_name']));
        return $md5;
    }

    /**
     * 获取临时路径
     * @return mixed
     * User kuoqi
     * Datetime 2022/3/30 14:04
     * Remark
     */
    public function getTmpname(){
        return $this->arraybyform['tmp_name'];
    }

    /**
     * 判定文件为excel
     * createby kuoqi at 2022/9/29 11:14
     * @return bool
     */
    public function isExcel(){
        if(!in_array($this->arraybyform['type'],[
            'application/octet-stream',
            'application/vnd.ms-excel',
            'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
        ])){
            $this->errmsg = 'file_mime not in list mime with '.$this->arraybyform['type'].' and library is '.json_encode($this->mimelist);
            $this->is_valied = false;
            return false;
        }
        return true;
    }
	
}